/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package fr.adama.controller;

import fr.adama.dto.AdherentDTO;
import fr.adama.dto.ContratDTO;
import fr.adama.dto.EmployeDTO;
import fr.adama.dto.ModelePaieDTO;
import fr.adama.entite.Contrat;
import fr.adama.entite.modele.ModelePaie;
import fr.adama.entite.typePerso.EtatContrat;
import fr.adama.service.AdherentService;
import fr.adama.service.ContratService;
import fr.adama.service.EmployeService;
import fr.adama.service.ModeleBulletinPaieService;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.validation.Valid;
import org.hibernate.exception.ConstraintViolationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

/**
 *
 * @author avisto
 */
@Controller
public class ContratController {

    private static final Logger logger = LoggerFactory.getLogger(AdherentController.class);
    SimpleDateFormat dateFormat = new SimpleDateFormat("dd MM yyyy");
    @Autowired
    private ContratService contratService;
    @Autowired
    private AdherentService adherentService;
    @Autowired
    private ModeleBulletinPaieService modelPaieService;

    @Autowired
    private EmployeService employeService;

    @Autowired
    private MessageSource messageSource;

    @ModelAttribute("listModelPaie")
    public List<ModelePaieDTO> modelePaies() {
        return modelPaieService.findAll(ModelePaie.class, ModelePaieDTO.class);
    }

    @RequestMapping("/contrat/index.do")
    public ModelAndView index() {
        return new ModelAndView("contrat/index");
    }

    @RequestMapping(method = RequestMethod.GET, value = "/contrat/add.do")
    public String addEmploye(ModelMap model) {

        ContratDTO contrat = new ContratDTO();
        model.addAttribute("contrat", contrat);
        return "contrat/add";
    }

    @RequestMapping(method = RequestMethod.GET, value = "/contrat/list.do")
    public ModelAndView listContrat() {
        List<ContratDTO> listContrat = contratService.findAll(Contrat.class, ContratDTO.class);

        return new ModelAndView("contrat/list", "listContrat", listContrat);

    }

    @RequestMapping(method = RequestMethod.GET, value = "/contrat/show.do")
    public ModelAndView getContratById(@RequestParam(required = true, value = "id") Long id) {
        ContratDTO contrat = contratService.getById(id, Contrat.class, ContratDTO.class);

        return new ModelAndView("contrat/show", "contrat", contrat);
    }

    @RequestMapping(value = "/contrat/searchAdherent.do", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
    @ResponseBody
    public List<AdherentDTO> searchAdherent(AdherentDTO adherent) {

        return adherentService.searchByEntity(adherent);
    }

    @RequestMapping(value = "/contrat/searchEmploye.do", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
    @ResponseBody
    public List<EmployeDTO> searchEmploye(EmployeDTO employe) {

        return employeService.searchByEntity(employe);
    }

    @RequestMapping(method = RequestMethod.POST, value = "/contrat/add.do")
    public ModelAndView insertContrat(@RequestParam("adherentRecherche") String adherent, @RequestParam("employeRecherche") String employe, @Valid @ModelAttribute("contrat") ContratDTO contratDto, BindingResult result, RedirectAttributes redirectAttributes, Locale locale) {

        if (result.hasErrors()) {
            Map<String, Object> map = new HashMap<>();
            map.put("contrat", contratDto);
            map.put("adherentRecherche", adherent);
            map.put("employeRecherche", employe);
            return new ModelAndView("contrat/add", map);
        }

        try {
            logger.info("Ajout d'un contrat entre adherent.id={} et employe.id={}", contratDto.getAdherent().getId().toString(), contratDto.getEmploye().getId());
            
            contratDto.setEtatContrat(EtatContrat.actif);
            contratDto = contratService.add(contratDto, Contrat.class);
            redirectAttributes.addFlashAttribute("SUCCESS_MESSAGE", messageSource.getMessage("Contrat.add.success", new String[]{""}, new Locale("fr")));
        } catch (DataIntegrityViolationException ex) {
            logger.error("Erreur d'ajout d'un contrat", ex);
            if (ex.getCause() instanceof ConstraintViolationException) {
                ConstraintViolationException cdts = (ConstraintViolationException) ex.getCause();
                if (cdts.getConstraintName().equalsIgnoreCase("CONTRATADHERENTEMPLOYEEXISTE")) {
                    ObjectError error = new ObjectError("employe", messageSource.getMessage("Contrat.add.error.contrat.exist",
                            new String[]{}, new Locale("fr")));
                    result.addError(error);
                    Map<String, Object> map = new HashMap<>();
                    map.put("contrat", contratDto);
                    map.put("adherentRecherche", adherent);
                    map.put("employeRecherche", employe);
                    return new ModelAndView("contrat/add", map);
                }

            } else {
                logger.error("Une erreur lors de l'ajout d'un adhérent", ex);
            }
        }
        return new ModelAndView("redirect:/contrat/show.do", "id", contratDto.getId());
    }

    @RequestMapping(method = RequestMethod.GET, value = "/contrat/update.do")
    public ModelAndView update(@RequestParam(required = true, value = "id") Long id) {
        ContratDTO contrat = contratService.getById(id, Contrat.class, ContratDTO.class);

        return new ModelAndView("contrat/update", "contrat", contrat);
    }

    @RequestMapping(method = RequestMethod.POST, value = "/contrat/update.do")
    public ModelAndView modifier(@Valid @ModelAttribute("contrat") ContratDTO contratDto, BindingResult result, RedirectAttributes redirectAttributes, Locale locale) {
        if (result.hasErrors()) {

            return new ModelAndView("contrat/update", "contrat", contratDto);
        }
        logger.info("Mis a jour d'un contrat entre adherent.id={} et employe.id={}", contratDto.getAdherent().getId().toString(), contratDto.getEmploye().getId());

        contratService.update(contratDto, Contrat.class);
        redirectAttributes.addFlashAttribute("SUCCESS_MESSAGE", messageSource.getMessage("Contrat.update.success", new String[]{""}, new Locale("fr")));
        return new ModelAndView("redirect:/contrat/show.do", "id", contratDto.getId());
    }

    @RequestMapping(method = RequestMethod.GET, value = "/contrat/search.do")
    public String search(ModelMap model) {
        ContratDTO contrat = new ContratDTO();
        model.addAttribute("contrat", contrat);
        return "contrat/search";
    }

    @RequestMapping(method = RequestMethod.POST, value = "/contrat/search.do")
    public ModelAndView search(@ModelAttribute("contrat") ContratDTO contratDto) {
        Map<String, Object> map = new HashMap<>();
        map.put("contrat", contratDto);
        map.put("listAdherent", adherentService.searchByEntity(contratDto.getAdherent()));
        map.put("listEmploye", employeService.searchByEntity(contratDto.getEmploye()));
        return new ModelAndView("contrat/search", map);
    }
}
